package com.framework.dbs.dao.impl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.ibatis.SqlMapClientTemplate;

import com.framework.bas.exception.BasException;
import com.framework.bas.util.UtilReflect;
import com.framework.dbs.dao.IDataBase;
import com.framework.dbs.orm.IBatisSqlExecutor;
import com.framework.dbs.vo.BaseObject;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;

@SuppressWarnings({"unchecked","unused"})
public class DataBaseImpl implements IDataBase {
	
	protected final Log logger = LogFactory.getLog(this.getClass());
    private SessionFactory sessionFactory;
    private DataSource dataSource;
    private SqlMapClient sqlMapClient;
    private SqlMapClientTemplate sqlMapClientTemplate;
    private HibernateTemplate hibernateTemplate;
    private JdbcTemplate jdbcTemplate;
    private SqlExecutor sqlExecutor;

	public DataSource getDataSource() {
		return dataSource;
	}

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public SqlMapClient getSqlMapClient() {
		return sqlMapClient;
	}

	public void setSqlMapClient(SqlMapClient sqlMapClient) {
		this.sqlMapClient = sqlMapClient;
	}

	public SqlExecutor getSqlExecutor() {
		return sqlExecutor;
	}

	public void setSqlExecutor(SqlExecutor sqlExecutor) {
		this.sqlExecutor = sqlExecutor;
	}
	
	public void setEnableCustomizedPaged(boolean enableCustomizedPaged) {
        if(sqlExecutor instanceof IBatisSqlExecutor)
        {
            ((IBatisSqlExecutor)sqlExecutor).setEnableCustomizedPaged(enableCustomizedPaged);
        }
    }

	/**
	 * Bean初始化
	 * 反射方式注入sqlExecutor
	 */
    public void doInit() throws Exception {
        if(sqlExecutor != null) {
            SqlMapClient sqlMapClient = getSqlMapClientTemplate().getSqlMapClient();
            if(sqlMapClient instanceof ExtendedSqlMapClient) {
            	UtilReflect.setFieldValue(((ExtendedSqlMapClient)sqlMapClient).getDelegate(), "sqlExecutor", com.ibatis.sqlmap.engine.execution.SqlExecutor.class, sqlExecutor);
            }
        }
    }

	/**
	 * 创建数据连接
	 * @param 
	 * @return Connection sql连接
	 */
	public Connection getConnection() throws BasException {
		Connection rs = null;
        try {
            rs = dataSource.getConnection();
        }catch(SQLException se) {
            throw new BasException("数据资源出错");
        }
        return rs;
	}
	
	/**
	 * 获取HibernateTemplate模板
	 * @param 
	 * @return HibernateTemplate
	 */
    public HibernateTemplate getHibernateTemplate() throws BasException {
    	if(hibernateTemplate == null) {
            hibernateTemplate = new HibernateTemplate(sessionFactory);
        }
        return hibernateTemplate;
    }
    
    /**
	 * 获取JdbcTemplate模板
	 * @param 
	 * @return JdbcTemplate
	 */
    public JdbcTemplate getJdbcTemplate() throws BasException {
    	if(jdbcTemplate == null) {
    		jdbcTemplate = new JdbcTemplate(dataSource);
    	}
    	return jdbcTemplate;
    }

    /**
	 * 获取SqlMapClientTemplate模板
	 * @param 
	 * @return SqlMapClientTemplate
	 */
    public SqlMapClientTemplate getSqlMapClientTemplate() throws BasException {
    	if(sqlMapClientTemplate == null) {
            sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
        }
        return sqlMapClientTemplate;
    }
	
	/**
	 * Hibernate保存对象
	 * @param serialObject 序列化对象
	 * @return int 保存数量个数
	 */
	public int save(BaseObject serialObject) throws BasException {
		int rs = 0;
        getHibernateTemplate().save(serialObject);
        rs = 1;
        return rs;
	}

	/**
	 * Hibernate-删除对象
	 * @param BaseObject 序列化对象
	 * @return int 删除数量个数
	 */
	public int delete(BaseObject serialObject) throws BasException {
		int rs = 0;
        getHibernateTemplate().delete(serialObject);
        rs = 1;
        return rs;
	}
	
	/**
	 * Hibernate-更新对象
	 * @param BaseObject 序列化对象
	 * @return int 更新数量个数
	 */
	public int update(BaseObject serialObject) throws BasException {
		int rs = 0;
        getHibernateTemplate().update(serialObject);
        rs = 1;
        return rs;
	}

	/**
	 * Hibernate-主键删除对象
	 * @param Class 对象VO类
	 * @param Serializable 序列化主键
	 * @return int 删除数量个数
	 */
	public int deleteByID(Class class1, Serializable serializable) throws BasException {
		int rs = 0;
        getHibernateTemplate().delete(findByID_Hibernate_Get(class1, serializable));
        rs = 1;
        return rs;
	}
	
	/**
	 * Hibernate-LOAD主键查询对象
	 * @param Class 对象VO类
	 * @param Serializable 序列化主键
	 * @return SerialObject 对象VO
	 */
    public <T extends BaseObject> T findByID_Hibernate_Load(Class class1, Serializable serializable) throws BasException {
    	T vo = null;
        vo = (T)getHibernateTemplate().load(class1, serializable);
        if(vo != null) {
            getHibernateTemplate().getSessionFactory().getCurrentSession().refresh(vo);
        }
        return vo;
    }

    /**
	 * Hibernate-GET查询对象
	 * @param Class 对象VO类
	 * @param Serializable 序列化主键
	 * @return SerialObject 对象VO
	 */
    public <T extends BaseObject> T findByID_Hibernate_Get(Class class1, Serializable serializable) throws BasException {
    	T vo = null;
    	vo = (T)getHibernateTemplate().get(class1, serializable);
    	if(vo != null){
    		getHibernateTemplate().getSessionFactory().getCurrentSession().refresh(vo);
    	}
    	return vo;
    }
    
    /**
	 * Hibernate-FIND查询所有对象
	 * @param Class 对象VO类
	 * @return List 对象VO集合SerialObject
	 */
    public <T extends BaseObject> List<T> findAll_Hibernate_Object(Class class1) throws BasException {
    	return (List<T>)getHibernateTemplate().loadAll(class1);
    }
	
	
	/**
	 * Hibernate-命名HQL删除对象
	 * @param String Hibernate-命名HQL定义
	 * @param Object[] 参数数组
	 * @return int 删除数量个数
	 */
	public int delete_Hibernate_NamedQuery(final String s, final Object params[]) throws BasException {
		int rs = 0;
        rs = ((Integer)getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
                Query queryCMd = session.getNamedQuery(s);
                String queryString = queryCMd.getQueryString();
                Query sqlq = session.createQuery(queryString);
                int length = params.length;
                for(int i = 0; i < length; i++) {
                    sqlq.setParameter(i, params[i]);
                }
                int rtn = sqlq.executeUpdate();
                return new Integer(rtn);
            }
        })).intValue();
        return rs;
	}
	
	/**
	 * Hibernate-命名HQL更新对象
	 * @param String Hibernate-命名HQL定义
	 * @param Object[] 参数数组
	 * @return int 删除数量个数
	 */
	public int update_Hibernate_NamedQuery(final String s, final Object params[]) throws BasException {
		int rs = 0;
        rs = ((Integer)getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
                Query queryCMd = session.getNamedQuery(s);
                String queryString = queryCMd.getQueryString();
                Query sqlq = session.createQuery(queryString);
                int length = params.length;
                for(int i = 0; i < length; i++) {
                    sqlq.setParameter(i, params[i]);
                }
                int rtn = sqlq.executeUpdate();
                return new Integer(rtn);
            }
        })).intValue();
        return rs;
	}

    /**
	 * Hibernate-命名HQL主键查询对象
	 * @param String Hibernate-命名HQL定义
	 * @param Serializable 序列化主键
	 * @return SerialObject 对象VO
	 */
    public <T extends BaseObject> T findByID_Hibernate_NamedQuery(String s, Serializable serializable) throws BasException {
    	List<T> list = (List<T>)getHibernateTemplate().findByNamedQuery(s, serializable);
        T vo = null;
        for(T mk : list){
        	vo = mk;
        }
        if(vo != null) {
            getHibernateTemplate().getSessionFactory().getCurrentSession().refresh(vo);
        }
        return vo;
    }
    
    /**
	 * Hibernate-命名HQL主键查询所有对象
	 * @param String Hibernate-命名HQL定义
	 * @param Object[] 参数值集合
	 * @param int offset偏移起始
	 * @param int size记录数
	 * @param boolean 是否返回记录数
	 * @return Object[] 记录list&记录数size
	 */
    public Object[] find_Hibernate_NamedQuery(final String s, final Object params[], final int offset, 
    		final int size, final boolean isTotalSize) throws BasException {
    	return (Object[])getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(org.hibernate.Session session) throws HibernateException, SQLException {
                Query query = session.getNamedQuery(s);
                setQueryParameter(query, params);
                if(offset >= 0 && size > 0) {
                    query.setFirstResult(offset);
                    query.setMaxResults(size);
                }
                List result = query.list();
                Integer count = Integer.valueOf("0");
                if(isTotalSize && !result.isEmpty()) {
                    String queryString = query.getQueryString();
                    String countQueryString = "select count(*) from " + queryString.substring(queryString.toLowerCase().indexOf("from") + 5);
                    Query countQuery = session.createSQLQuery(countQueryString);
                    setQueryParameter(countQuery, params);
                    count = new Integer(String.valueOf(countQuery.list().get(0)));
                }
                Object objs[] = {result, count};
                return ((Object) (objs));
            }
            private void setQueryParameter(Query query, Object params[]) {
                if(params != null) {
                    for(int i = 0; i < params.length; i++) {
                        query.setParameter(i, params[i]);
                    }
                }
            }
        });
    }
    
    /**
	 * Hibernate-命名HQL查询所有对象
	 * @param String Hibernate-命名HQL定义
	 * @return List 对象VO集合SerialObject
	 */
    public <T extends BaseObject> List<T> findAll_Hibernate_NamedQuery(String s) throws BasException {
        return (List<T>)getHibernateTemplate().findByNamedQuery(s);
    }

	/**
	 * iBatis-保存对象
	 * @param String iBatis-SQL定义
	 * @param Object[] 参数数组
	 * @return int 保存数量个数
	 */
	public int save_iBatis(String s, Object params[]) throws BasException {
		int rs = 0;
        if(params == null || params.length == 0) {
            getSqlMapClientTemplate().insert(s, null);
        } else {
            getSqlMapClientTemplate().insert(s, params[0]);
        }
        rs = 1;
        return rs;
	}
	
	/**
	 * iBatis-删除对象
	 * @param String iBatis-SQL定义
	 * @param Object[] 参数数组
	 * @return int 删除数量个数
	 */
	public int delete_iBatis(String s, Object params[]) throws BasException {
		int rs = 0;
        if(params == null || params.length == 0) {
            getSqlMapClientTemplate().delete(s, null);
        } else {
            getSqlMapClientTemplate().delete(s, params[0]);
        }
        rs = 1;
        return rs;
	}
	
	/**
	 * iBatis-更新对象
	 * @param String iBatis-SQL定义
	 * @param Object[] 参数数组
	 * @return int 更新数量个数
	 */
	public int update_iBatis(String s, Object params[]) throws BasException {
		int rs = 0;
		if(params == null || params.length == 0) {
            getSqlMapClientTemplate().update(s, null);
        } else {
            getSqlMapClientTemplate().update(s, params[0]);
        }
        rs = 1;
        return rs;
	}
	
	/**
	 * iBatis-查询所有对象
	 * @param String iBatis-SQL定义
	 * @return List 对象集合
	 */
	public <T> List<T> find_iBatis(String s) throws BasException {
		return (List<T>)getSqlMapClientTemplate().queryForList(s);
	}
	
	/**
	 * iBatis-查询指定范围所有对象
	 * @param String iBatis-SQL定义
	 * @param Object param参数
	 * @param int offset偏移起始
	 * @param int size记录数
	 * @return List 对象集合
	 */
	public <T> List<T> find_iBatis(String s, Object param, int offset, int size) throws BasException {
		setEnableCustomizedPaged(true);
        return (List<T>)getSqlMapClientTemplate().queryForList(s, param, offset, size);
	}
	
	/**
	 * iBatis-查询所有对象
	 * @param String iBatis-SQL定义
	 * @param Object 参数
	 * @return List 对象集合
	 */
	public <T> List<T> find_iBatis(String s, Object obj) throws BasException {
		setEnableCustomizedPaged(true);
		return getSqlMapClientTemplate().queryForList(s, obj);
		//return find_iBatis(s, obj, 0, 0xfff0bdc1);
	}
	
	/**
	 * JDBC-保存对象
	 * @param String JDBC-SQL语句
	 * @param Object[] 参数数组
	 * @return int 保存数量个数
	 */
	public int save_JDBC(String s, Object aobj[]) throws BasException {
		int rs = 0;
        getJdbcTemplate().execute(s);
        rs = 1;
        return rs;
	}
	
	/**
	 * JDBC-删除对象
	 * @param String JDBC-SQL语句
	 * @param Object[] 参数数组
	 * @return int 删除数量个数
	 */
	public int delete_JDBC(String s, Object aobj[]) throws BasException {
		int rs = 0;
        getJdbcTemplate().execute(s);
        rs = 1;
        return rs;
	}
	
	/**
	 * JDBC-删除对象
	 * @param String JDBC-SQL语句
	 * @param Object[] 参数数组
	 * @return int 删除数量个数
	 */
	public int update_JDBC(String s, final Object aobj[]) throws BasException {
		int rs = 0;
        getJdbcTemplate().execute(s, new PreparedStatementCallback<Integer>() {
			public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
				if(aobj!=null){
					for(int i=0;i<aobj.length;i++){
						ps.setObject(i, aobj[i]);
					}
				}
				ps.execute();
				return 1;
			}
        	
		});
        rs = 1;
        return rs;
	}
	
	/**
	 * JDBC-查询所有对象
	 * @param String JDBC-SQL语句
	 * @return List 对象集合
	 */
	public List findAll_JDBC(String s) throws BasException {
		return getJdbcTemplate().queryForList(s);
	}
	
	/**
	 * JDBC-执行存储过程
	 * @param String 过程名称
	 * @param Map 系统参数
	 * @return Map 过程结果
	 */
	public Map runProcedure_JDBC(String procedureName, Map param) throws BasException {
		Map result = null;
		SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(this.getDataSource());
		simpleJdbcCall.setProcedureName(procedureName);
		SqlParameterSource in = new MapSqlParameterSource().addValues(param);
		result = simpleJdbcCall.execute(in);
		simpleJdbcCall = null;
		return result;
	}

}
